package src.A_JavaBase;

public class Demo01 {
    public static void main(String[] args) {

        /*
        * 1bit表示1位
        * 1Byte表示一个字节 1B = 8b
        * 1024B = 1KB
        * 1024KB = 1M
        * 1024M = 1G
        * */

        String a = "a";

        //八大基本数据类型
        byte num1 = 10;
        short num2 = 100;
        int num3 = 10_0000_0000;
        long num4 = 6666666666666666666l;
        float num5 = 66666666666666666666666666666666666666.666f;
        double num6 = 66666666666666666666666666666666666666666666666666666666.666666666;
        char name = '我';
        boolean flag = true;

        //整数拓展：  进制     二进制0b     十进制       八进制0        十六进制0x
        int i = 10;
        int i2 = 010; //八进制0
        int i3 = 0x10; //十六进制0x  0-9 A-F=10-15
        System.out.println("===================整数拓展========================");
        System.out.println(i+"\t"+i2+"\t"+i3);
        System.out.println(1+2+""); //拼接细节
        System.out.println(""+1+2);

        //浮点数拓展   涉及计算不用浮点数，用BigDecimal类（浮点数会先转化为二进制然后计算，但是它们两个精度是有限的所以有些数转化成二进制会不精准，BigDecimal类是把该数乘以数倍变成整数再计算）
        float f = 0.1f;    //0.1
        double d = 1.0/10; //0.1
        System.out.println("===================浮点数拓展========================");
        System.out.print(f+"\t"+d+"\t");
        System.out.print(f==d); //false
        System.out.print("\t");
        f = 11111111111111111f;
        float f1 = f+1;
        System.out.println(f==f1); //true

        //字符拓展  所有字符本质是数字，对应Unicode编码表
        char c1 = 'a' , c2 = '中' , c3 = '\u0061' , c4 = '\u0000';//char的默认值，空格符
        System.out.println("===================字符拓展========================");
        System.out.print(c1+"\t"+c2+"\t"+(int)c1+"\t"+(int)c2+"\t"+c3+"\t"+c4+"\n");

        //移位运算
        System.out.println("===================移位运算========================");
        /*
        * 计算机支持两种移位运算，假设操作数为x，移动的位数为k
        * 向左移位是 x << k，左移位会对输入的操作数舍弃最高的k位，并在右端补k个0
        * 向右移位是 x >> k，右移位运算却分为两种情况，分别是逻辑右移和算术右移（也叫无符号右移和符号右移）
        * 在逻辑右移中，会对操作数舍弃最低的k位，并在左端补k个0，在算术运算中，则对操作数舍弃最低的k位，并在左端补k个最高有效位的值
        * */

        //左移位运算。相当于做乘法运算，乘积因子为 2^k。例如，我们执行149 << 4，相当于执行了 149*16 = 2384
        //正数左位移
        System.out.print ((149 << 4)+"\t");
        System.out.print (Integer.toBinaryString(149)+"\t");
        System.out.println (Integer.toBinaryString(149 << 4));
        /*
        149 << 4 的计算过程如下：
        输入：      149
        转为二进制： 10010101
        展开32位:   00000000 00000000 00000000 10010101
        丢弃最高4位: 0000 00000000 00000000 10010101
        右端补4个0： 0000 00000000 00000000 10010101 0000
        忽略符号位： 10010101 0000
        * */
        //负数左位移
        System.out.print((-149 << 4)+"\t");
        System.out.print(Integer.toBinaryString(-149)+"\t");
        System.out.println(Integer.toBinaryString(-149 << 4));
        /*
        -149 << 4 的计算过程如下：
        输入：       -149
        转为二进制：  11111111 11111111 11111111 01101011  (ps: 绝对值二进制取反再加1。)
        丢弃最高4位:  1111 11111111 11111111 01101011
        右端补4个0：  1111 11111111 11111111 01101011 0000
        以上是个负数二进制，现要转成十进制，按照以下三步进行：     (ps: 也可以先取反再加1。)
                    1111 11111111 11111111 01101010 1111（减1）
                    0000 00000000 00000000 10010101 0000（取反）
                    -10010101 0000（忽略符号位，并添负号）
        转为十进制： -2384
        * */

        //右位移运算，右移运算也相当于做除法运算，被除数为 2^k。例如，我们执行149 >> 4，相当于执行了 149/16 = 9。
        //正数右位移
        //对于正数来说，逻辑右移和算术右移没有任何区别，因为都是在左端补0。
        System.out.print((149 >> 4)+"\t");  //算术右移
        System.out.print(Integer.toBinaryString(149)+"\t");
        System.out.println(Integer.toBinaryString(149 >> 4));
        System.out.print((149 >>> 4)+"\t");  //逻辑右移
        System.out.print(Integer.toBinaryString(149)+"\t");
        System.out.println(Integer.toBinaryString(149 >>> 4));
        /*
        149 >> 4 计算过程：
        输入：        149
        转为二进制：   10010101
        展开32位：    00000000 00000000 00000000 10010101
        丢弃最低4位：  00000000 00000000 00000000 1001
        左端补4个0：  0000 00000000 00000000 00000000 1001
        忽略符号位：  1001
        转为十进制：  9
        149 >>> 4 的计算过程和上面完全一样，左端都是补4个0，所以打印效果当然是一致的。
        * */
        //负数右位移
        //此时逻辑右移和算术右移将产生较大区别。由于负数高位是1，所以算术右移和逻辑右移在左端分别补1和0
        System.out.print ((-149 >> 4)+"\t");  //负数的算术右移
        System.out.print(Integer.toBinaryString(149)+"\t");
        System.out.println (Integer.toBinaryString ( -149 >> 4 )+"\t");
        System.out.print ((-149 >>> 4)+"\t"); //负数的逻辑右移
        System.out.print(Integer.toBinaryString(149)+"\t");
        System.out.println (Integer.toBinaryString ( -149 >>> 4 ));
        /*
        a）-149 >> 4 计算过程（负数的算术右移）：
        输入：       -149
        转为二进制:  11111111 11111111 11111111 01101011         (ps: 绝对值二进制取反再加1。)
        丢弃最低4位: 11111111 11111111 11111111 0110
        左端补4个1： 1111 11111111 11111111 11111111 0110
        相应十进制:  -0000 00000000 00000000 00000000 0101   (ps: 减1，取反，添负号。)
        转为十进制： -10
        可以看出，我们第4步和第6步运算结果和代码打印的前两行完全一致。
        b）-149 >>> 4 计算过程（负数的逻辑右移）：
        输入:       -149
        转为二进制:  11111111 11111111 11111111 01101011       (ps: 绝对值二进制取反再加1。)
        丢弃最低4位: 11111111 11111111 11111111 0110
        左端补4个0： 0000 11111111 11111111 11111111 0110
        转为十进制： 268435446
        * */

        /*
        * 移位运算小结：
        149 << 4 	  去4个最高位，最低位补4个0 ==》149*2^4=149*16
        -149 << 4     去4个最高位，最低位补4个0 ==》-149*2^4=-149*16

        149 >>> 4     去4个最低位，最高位补4个0 ==》149/2^4=149/16   (正整数逻辑右移)
        149 >> 4      去4个最低位，最高位补4个0 ==》149/2^4=149/16   (正整数算术右移)

        -149 >>> 4    去4个最低位，最高位补4个0   (负整数逻辑右移)
        -149 >> 4     去4个最低位，最高位补4个1   (负整数算术右移)
        * */
    }
}
